/*
 * Copyright 2016 jeasonlzy(廖子尧)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lzy.okgo.convert;

import ohos.agp.components.Image;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * ================================================
 * 作    者：jeasonlzy（廖子尧）
 * 版    本：1.0
 * 创建日期：16/9/11
 * 描    述：字符串的转换器
 * 修订历史：
 * ================================================
 */
public class BitmapConvert implements Converter<PixelMap> {

    private int maxWidth;
    private int maxHeight;
    private PixelFormat decodeConfig;
    private Image.ScaleMode scaleType;

    public BitmapConvert() {
        this(1000, 1000, PixelFormat.ARGB_8888, Image.ScaleMode.INSIDE);
    }

    public BitmapConvert(int maxWidth, int maxHeight) {
        this(maxWidth, maxHeight, PixelFormat.ARGB_8888, Image.ScaleMode.INSIDE);
    }

    public BitmapConvert(int maxWidth, int maxHeight, PixelFormat decodeConfig, Image.ScaleMode scaleType) {
        this.maxWidth = maxWidth;
        this.maxHeight = maxHeight;
        this.decodeConfig = decodeConfig;
        this.scaleType = scaleType;
    }

    @Override
    public PixelMap convertResponse(Response response) throws Throwable {
        ResponseBody body = response.body();
        if (body == null) return null;
        return parse(body.bytes());
    }

    /**
     * 这里把 byte数组转PixelMap
     *
     * @param byteArray 字节数组
     * @return PixelMap
     */
    private PixelMap parse(byte[] byteArray) {
        if (byteArray == null || byteArray.length == 0) {
            return null;
        }

        ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
        srcOpts.formatHint = "image/*";
        ImageSource imageSource = ImageSource.create(byteArray, srcOpts);

        ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
        decodingOpts.desiredSize = new Size(0, 0);
        decodingOpts.desiredRegion = new Rect(0, 0, 0, 0);
        decodingOpts.desiredPixelFormat = decodeConfig;

        return imageSource.createPixelmap(decodingOpts);
    }

    // 这里把字节数组转PixelMap
//    private Bitmap parse(byte[] byteArray) throws OutOfMemoryError {
//        BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
//        Bitmap bitmap;
//        if (maxWidth == 0 && maxHeight == 0) {
//            decodeOptions.inPreferredConfig = decodeConfig;
//            bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, decodeOptions);
//        } else {
//            decodeOptions.inJustDecodeBounds = true;
//            BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, decodeOptions);
//            int actualWidth = decodeOptions.outWidth;
//            int actualHeight = decodeOptions.outHeight;
//
//            int desiredWidth = getResizedDimension(maxWidth, maxHeight, actualWidth, actualHeight, scaleType);
//            int desiredHeight = getResizedDimension(maxHeight, maxWidth, actualHeight, actualWidth, scaleType);
//
//            decodeOptions.inJustDecodeBounds = false;
//            decodeOptions.inSampleSize = findBestSampleSize(actualWidth, actualHeight, desiredWidth, desiredHeight);
//            Bitmap tempBitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, decodeOptions);
//
//            if (tempBitmap != null && (tempBitmap.getWidth() > desiredWidth || tempBitmap.getHeight() > desiredHeight)) {
//                bitmap = Bitmap.createScaledBitmap(tempBitmap, desiredWidth, desiredHeight, true);
//                tempBitmap.recycle();
//            } else {
//                bitmap = tempBitmap;
//            }
//        }
//        return bitmap;
//    }
//
//    private static int getResizedDimension(int maxPrimary, int maxSecondary, int actualPrimary, int actualSecondary, ImageView.ScaleType scaleType) {
//
//        // If no dominant value at all, just return the actual.
//        if ((maxPrimary == 0) && (maxSecondary == 0)) {
//            return actualPrimary;
//        }
//
//        // If ScaleType.FIT_XY fill the whole rectangle, ignore ratio.
//        if (scaleType == ImageView.ScaleType.FIT_XY) {
//            if (maxPrimary == 0) {
//                return actualPrimary;
//            } else {
//                return maxPrimary;
//            }
//        }
//
//        // If primary is unspecified, scale primary to match secondary's scaling ratio.
//        if (maxPrimary == 0) {
//            double ratio = (double) maxSecondary / (double) actualSecondary;
//            return (int) (actualPrimary * ratio);
//        }
//
//        if (maxSecondary == 0) {
//            return maxPrimary;
//        }
//
//        double ratio = (double) actualSecondary / (double) actualPrimary;
//        int resized = maxPrimary;
//
//        // If ScaleType.CENTER_CROP fill the whole rectangle, preserve aspect ratio.
//        if (scaleType == ImageView.ScaleType.CENTER_CROP) {
//            if ((resized * ratio) < maxSecondary) {
//                resized = (int) (maxSecondary / ratio);
//            }
//            return resized;
//        }
//
//        if ((resized * ratio) > maxSecondary) {
//            resized = (int) (maxSecondary / ratio);
//        }
//        return resized;
//    }

    private static int findBestSampleSize(int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) {
        double wr = (double) actualWidth / desiredWidth;
        double hr = (double) actualHeight / desiredHeight;
        double ratio = Math.min(wr, hr);
        float n = 1.0f;
        while ((n * 2) <= ratio) {
            n *= 2;
        }
        return (int) n;
    }
}
